
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Diagnostics;

using Swaf.BizObj;
using Swaf.Container;


namespace Swaf.Logging
{
    /// <summary>
    /// Summary description for Log.
    /// </summary>
    public class Log : BaseLog, ILog
    {
        protected int m_defaultLevel;
        protected bool m_loadingComplete = false;

        public Log(string groupName, int defaultLevel, int notifyThreshold)
            : base(groupName)
        {
            m_defaultLevel = defaultLevel;
            m_notifyThreshold = notifyThreshold;
        }

        #region ILog Members
        public bool LogCaller
        {
            get { return m_logCaller; }
            set { m_logCaller = value; }
        }
        public int NotifyThreshold
        {
            get { return m_notifyThreshold; }
            set { m_notifyThreshold = value; }
        }

        public int DefaultLevel
        {
            get { return m_defaultLevel; }
            set { m_defaultLevel = value; }
        }

        public void write(string info, params object[] changes)
        {
            notify(m_defaultLevel, changes.Length == 0 ? info : String.Format(info, changes), false);
        }
        public void write(INameAddressSupport info)
        {
            notify(m_defaultLevel, info, false);
        }

        public void println(string info)
        {
            notify(m_defaultLevel, info, true);
        }
        public void println(INameAddressSupport info)
        {
            notify(m_defaultLevel, info, false);
        }

        public void println(string info, params object[] changes)
        {
            notify(m_defaultLevel, changes.Length == 0 ? info : String.Format(info, changes), true);
        }

        public void println(int level, string info)
        {
            notify(level, info, true);
        }
        public void println(LoggingLevels level, string info)
        {
            notify((int)level, info, true);
        }

        public void println(int level, string info, params object[] changes)
        {
            notify(level, changes.Length == 0 ? info : String.Format(info, changes), true);
        }
        public void println(int level, INameAddressSupport info)
        {
            notify(level, info, true);
        }
        public void println(LoggingLevels level, string info, params object[] changes)
        {
            notify((int)level, changes.Length == 0 ? info : String.Format(info, changes), true);
        }
        public void println(LoggingLevels level, INameAddressSupport info)
        {
            notify((int)level, info, true);
        }
        #endregion
        protected void notify(int level, object message, bool newLine)
        {
            if (!(m_notifyThreshold < 0 || m_notifyThreshold > level))
            {
                //Note: No performance testing has been done on this.  It probably could be made much faster
                //with another round of work....
                IDictionary info = new Hashtable();
                info["level"] = level;
                if (message.GetType() == typeof(string))
                    info["message"] = !m_logCaller ? (string)message : string.Format("({0}) {1}", Cmn.getCaller(3), message);
                else
                {
                    try
                    {
                        if (!(message is IBizObj) || ((message is IBizObj) && (((IBizObj)message).containsField("caller"))))
                        {
                            ((INameAddressSupport)message).put("caller", Cmn.getCaller(3));
                        }
                    }
                    finally
                    {
                        info["message"] = message;
                    }
                }
                info["time"] = DateTime.Now;
                info["logCaller"] = m_logCaller;
                info["newLine"] = newLine;
                //Add bool to indicate whether this is a startup message or not!
                info["isStartup"] = Application.IsLoading;

                info["machineName"] = Environment.MachineName;

                IApplication app = Application.currentApp;
                if (app != null)
                {
                    if (app.resMgr != null)
                    {
                        info["applicationId"] = app.resMgr.resolve("$ApplicationId$");
                        info["applicationName"] = app.resMgr.resolve("$ApplicationName$");
                    }

                    if (app.securityMgr != null && app.securityMgr.currentPrincipal != null)
                    {
                        info["currentUser"] = app.securityMgr.currentPrincipal.userName;
                    }
                }

                if (!m_loadingComplete)
                {
                    //This code will only be called during startup so should not have any
                    //impact on normal logging calls except for one if statement.
                    m_loadingComplete = !Application.IsLoading;
                    //If we have actually finished loading, we need to clear the buffer so it does
                    //not hang around forever.
                    if (m_loadingComplete)
                        m_buffer.Clear();
                    else
                    {
                        lock (m_buffer)
                        {
                            m_buffer.Add(info);
                        }
                    }
                }
                this.notifyObservers(info);
            }
        }


    }
}
